using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace Noein
{
    public class Spatial
    {
        #region Fields

        private Vector3 position;
        public Vector3 Position
        {
            get { return position; }
        }
        public float X
        {
            get { return position.X; }
            set { MoveTo(new Vector3(value, position.Y, position.Z)); }
        }
        public float Y
        {
            get { return position.Y; }
            set { MoveTo(new Vector3(position.X, value, position.Z)); }
        }
        public float Z
        {
            get { return position.Z; }
            set { MoveTo(new Vector3(position.X, position.Y, value)); }
        }

        public float RotateX
        {
            set
            {
                this.Orientation =
                    Quaternion.Multiply(orientation, Quaternion.RotationYawPitchRoll(value, 0, 0));
            }
        }

        private Vector3 prevPosition;
        public Vector3 PreviousPosition
        {
            get { return prevPosition; }
        }

        private Quaternion orientation;
        public Quaternion Orientation
        {
            get { return orientation; }
            set
            { 
                orientation = value; 
                orientation.Normalize(); 
                orientationMatrix = Matrix.RotationQuaternion(value);
            }
        }

        private Matrix orientationMatrix;
        public Matrix OrientationMatrix
        {
            get { return orientationMatrix; }
        }

        public Matrix Transform
        {
            get
            {
                Matrix transform = Matrix.RotationQuaternion(orientation);
                transform.M41 = position.X;
                transform.M42 = position.Y;
                transform.M43 = position.Z;
                return transform;
            }
        }

        //private Geometry geometry;
        //public Geometry Geometry
        //{
        //    get { return geometry; }
        //}

        //private bool collidable;
        //public bool Collidable
        //{
        //    get { return collidable; }
        //    set
        //    {
        //        if (geometry == null && value)
        //        {
        //            throw new Exception("Cannot enable collision on object with undefined geometry!");
        //        }
        //        collidable = value;
        //    }
        //}

        #endregion

        public Spatial()
            : this(Vector3.Empty, Matrix.Identity)//, null)
        {
        }

        public Spatial(Vector3 position, Matrix orientation)//, Geometry geometry)
        {
            this.position = position;
            this.prevPosition = position;
            Orientation = Quaternion.RotationMatrix(orientation);
            //this.geometry = geometry;
            //Collidable = geometry != null;
        }

        public Spatial(Spatial spatial)
        {
            position = new Vector3(spatial.position.X, spatial.position.Y, spatial.position.Z);
            prevPosition = position;
            Orientation = Quaternion.RotationMatrix(spatial.Transform);
        }

        public void SetTransform(Device device)
        {
            device.Transform.World = Transform;
        }

        #region Modifiers

        public void rotateAxis(Vector3 axis, float angle)
        {
            Quaternion change = new Quaternion();
            change.RotateAxis(axis, angle);
            Orientation = Quaternion.Multiply(orientation, change);
        }

        public void MoveTo(Vector3 newPosition)
        {
            prevPosition = position;
            position = newPosition;
        }

        public void TeleportTo(Vector3 newPosition)
        {
            prevPosition = newPosition;
            position = newPosition;
        }

        public void CorrectTo(Vector3 newPosition)
        {
            position = newPosition;
        }

        #endregion
    }














































    public abstract class Geometry
    {
        //public const int RADIUS = 0;
        //public const int WIDTH = 0;
        //public const int HEIGHT = 1;
        //public const int DEPTH = 2;
        //public const int HALF_WIDTH = 3;
        //public const int HALF_HEIGHT = 4;
        //public const int HALF_DEPTH = 5;

        public abstract bool Collide(Spatial object1, Spatial object2, ref float u0, ref float u1);

        #region Geometry subclasses

        //public class CircularCylinder : Geometry
        //{
        //}

        //public class CircularCylindricalShell : Geometry
        //{
        //}

        //public class RectangularCylinder : Geometry
        //{
        //}

        public class Sphere : Geometry
        {
            private float radius;

            public Sphere(float radius)
            {
                this.radius = radius;
            }

            public override bool Collide(Spatial object1, Spatial object2, ref float u0, ref float u1)
            {
                throw new Exception("The method or operation is not implemented.");
            }
        }

        //public class SphericalShell : Geometry
        //{
        //}

        //public class Composite : Geometry
        //{
        //}

        //public class Mesh : Geometry
        //{
        //}

        #endregion
    }
}
